﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;

namespace AuktionsServer
{
	class Services
	{
		Auktion auktion;
        public delegate void BroadcastEventHandler(string besked);
        public event BroadcastEventHandler BroadcastEvent;
		public event BroadcastEventHandler BudIndkommet;
		bool hammerslagrun;
		bool førsteBud = true;
		bool lukket = true;
		object lukketLås = new object();

		public Services()
		{
			lukket = false;
		}

        public void BroadcastBesked(string besked)
        {
            if (this.BroadcastEvent != null)
                BroadcastEvent(besked);
        }

		/// <summary>
		/// Giver et bud til Auktionen
		/// </summary>
		/// <param name="bud">Budet der bliver givet</param>
		/// <param name="klientID">IDet på klienten som giver budet</param>
		/// <returns>Buddet sendes tilbage hvis budet er successfuldt, "underbud" hvis budet er under nuværende bud, eller "mindstebud" hvis budet er under mindstebuddet</returns>
		public string ModtagBud(int bud, int klientID)
		{
			lock (lukketLås)
			{
				//hvis auktionen er overstået
				if (lukket)
				{
					return "lukket";
				}
				//på det første bud skal Hammerslag startes
				if (førsteBud)
				{
					HammerslagStart();
					førsteBud = false;
				}
				string message = auktion.GivBud(bud, klientID);
				if (message != "underbud" && message != "mindstebud")
				{
					BudIndkommet(message);
				}
				return message;
			}
		}

		/// <summary>
		/// Opretter en ny auktion og tilknytter den til services.
		/// Åbner for at der kan bydes
		/// </summary>
		/// <returns>Det nyoprettede objekt returneres</returns>
		public Auktion StartAuktion()
		{			
			Console.Write("Auktionsobjekt: ");
			string auktionsobjekt = Console.ReadLine();
			Console.Write("Mindste bud: ");
			string mindstebud = Console.ReadLine();

			auktion = new Auktion(auktionsobjekt, Convert.ToInt32(mindstebud));
			
			Console.WriteLine("Auktion oprettet: " + auktion.Auktionsobjekt + ". Mindstebud: " + auktion.Mindstebud + "kr");
			
			førsteBud = true;
			lukket = false;
			
			BroadcastBesked(AuktionsInformation(1));
			
			return auktion;
		}

		/// <summary>
		/// Lukker auktionen og annoncerer vinderen.
		/// Er ikke trådsikret i sig selv. Skal trådsikres fra hvor den kaldes.
		/// </summary>
		public void LukAuktion()
		{
			lukket = true;
			hammerslagrun = false;
			BroadcastBesked("Solgt til %" + auktion.VinderID + "% for " + auktion.Bud + " kr");
			Console.WriteLine("Auktion afsluttet.");
			StartAuktion();
		}

		/// <summary>
		/// Starter en service som sender et broadcast til klienterne når der ikke har været nogen bud i 10 sekunder, derefter 5 sekunder og endelig 3 sekunder.
		/// </summary>
		public void HammerslagStart()
		{
			Thread hammerslagtråd = new Thread(HammerslagThread);
			hammerslagtråd.IsBackground = true;
			hammerslagtråd.Start();
			BudIndkommet += HammerslagReset;
		}

		private void HammerslagThread()
		{
			int hammerslag = 0;
			auktion.SidsteBud = DateTime.Now;

			hammerslagrun = true;
			
			while(hammerslagrun)
			{
				TimeSpan tidForløbet = DateTime.Now.Subtract(auktion.SidsteBud);
				if (tidForløbet.Seconds > 18)
				{
					if (hammerslag < 3)
					{
						lock (lukketLås)
						{
							Console.WriteLine("Tredje Hammerslag");
							BroadcastBesked("\r\nTredje");
							hammerslag = 3;
							LukAuktion();
						}
					}
				}
				else if (tidForløbet.Seconds > 15)
				{
					if (hammerslag < 2)
					{
						Console.WriteLine("Andet Hammerslag");
						BroadcastBesked("\r\nAnden\r\n");
						hammerslag = 2;
					}
				}
				else if (tidForløbet.Seconds > 10)
				{
					if (hammerslag < 1)
					{
						Console.WriteLine("Første Hammerslag");
						BroadcastBesked("\r\nFørste\r\n");
						hammerslag = 1;
					}
				}
				else
				{
					hammerslag = 0;
				}
			}
		}

		private void HammerslagReset(string message)
		{
			auktion.SidsteBud = DateTime.Now;
		}

		public void HammerslagStop()
		{
			hammerslagrun = false;
		}
        
		/// <summary>
		/// Returnerer en fler-linjet string med informationer om Auktionen
		/// </summary>
		/// <param name="sessionInt">0: Ny-ankommen klient til igangværende auktion 1: Meddelelse ved begyndelse af ny auktion</param>
		/// <returns></returns>
        public string AuktionsInformation(int sessionInt)
        {
			string message = "";
			//Preliminary
			if (sessionInt == 0)
			{
				message += "Velkommen til auktionshuset\r\n";
			}
			//Information om Auktionsobjekt
			if (sessionInt == 0)
			{
				message += "Nuværende ";
			}
			else if(sessionInt == 1)
			{
				message += "\r\nNyt ";
			}
			message += "auktionsobjekt: " + auktion.Auktionsobjekt + "\r\n";
			//Information om nuværende/mindste bud
			if (sessionInt == 0)
			{
				if (auktion.Bud != -1)
				{
					message += "Højeste bud: " + auktion.Bud;
				}
				else//Ingen har budt på auktionen endnu
				{
					message += "Mindstebud: " + auktion.Mindstebud;
				}
				
			}
			else if (sessionInt == 1)
			{
				message += "Mindstebud: " + auktion.Mindstebud;
			}
			message += "\r\n";
            return message;
        }
	}
}
